/*
 * @(#)MaintWorkflowStepAction.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.workflow.web;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.Crypt;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.MessageResourcesFactory;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemFunctionConstant;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.framework.bean.AbstractBaseObject;
import com.dcivision.framework.bean.ProtectedObject;
import com.dcivision.framework.bean.ProtectedResource;
import com.dcivision.framework.dao.ProtectedObjectDAObject;
import com.dcivision.framework.dao.ProtectedResourceDAObject;
import com.dcivision.framework.web.AbstractActionForm;
import com.dcivision.setup.dao.WorkingCalendarDAObject;
import com.dcivision.workflow.WorkflowErrorConstant;
import com.dcivision.workflow.bean.MtmWfStageWfStep;
import com.dcivision.workflow.bean.MtmWfStepFormRecord;
import com.dcivision.workflow.bean.MtmWfStepNotificationRule;
import com.dcivision.workflow.bean.MtmWfStepNotificationTarget;
import com.dcivision.workflow.bean.MtmWorkflowStepPriorityRule;
import com.dcivision.workflow.bean.MtmWorkflowStepUserActor;
import com.dcivision.workflow.bean.MtmWorkflowStepWorkflowStep;
import com.dcivision.workflow.bean.WorkflowAction;
import com.dcivision.workflow.bean.WorkflowRecord;
import com.dcivision.workflow.bean.WorkflowStage;
import com.dcivision.workflow.bean.WorkflowStep;
import com.dcivision.workflow.bean.WorkflowStepFormEquat;
import com.dcivision.workflow.bean.WorkflowStepParameterValue;
import com.dcivision.workflow.bean.WorkflowStepRoute;
import com.dcivision.workflow.core.AutomaticTaskFactory;
import com.dcivision.workflow.core.WorkflowOperationManager;
import com.dcivision.workflow.core.WorkflowProcessor;
import com.dcivision.workflow.core.WorkflowRetrievalManager;
import com.dcivision.workflow.core.WorkflowStepManager;
import com.dcivision.workflow.core.WorkflowStepOperationWarningMessageManager;
import com.dcivision.workflow.dao.MtmWfStageWfStepDAObject;
import com.dcivision.workflow.dao.MtmWfStepFormRecordDAObject;
import com.dcivision.workflow.dao.MtmWfStepNotificationRuleDAObject;
import com.dcivision.workflow.dao.MtmWfStepNotificationTargetDAObject;
import com.dcivision.workflow.dao.MtmWorkflowStepPriorityRuleDAObject;
import com.dcivision.workflow.dao.MtmWorkflowStepUserActorDAObject;
import com.dcivision.workflow.dao.MtmWorkflowStepWorkflowStepDAObject;
import com.dcivision.workflow.dao.WorkflowRecordDAObject;
import com.dcivision.workflow.dao.WorkflowStageDAObject;
import com.dcivision.workflow.dao.WorkflowStepDAObject;
import com.dcivision.workflow.dao.WorkflowStepFormEquatDAObject;
import com.dcivision.workflow.dao.WorkflowStepParameterValueDAObject;
import com.dcivision.workflow.dao.WorkflowStepRouteDAObject;

/**
  MaintWorkflowStepAction.java

  This class is for maint workflow step.

    @author          Angus Shiu
    @company         DCIVision Limited
    @creation date   29/07/2003
    @version         $Revision: 1.99.2.1 $
*/

public class MaintWorkflowStepAction extends com.dcivision.framework.web.AbstractMaintAction {

  public static final String REVISION = "$Revision: 1.99.2.1 $";


  public static final String WORKFLOW_STEP_TYPES = "workflowStepTypes";
  public static final String WORKFLOW_STEP_PARENT_LIST = "workflowStepParentList";
  private static final String HELPER_CLASS = "com.dcivision.workflow.core.WorkflowTaskProtectedFilterHelper";
  private static final String WORKFLOW_STEP_ERROR_NO_FOUND_STEPS = "errors.workflow.move_to_steps_can_not_found";

  /** Creates a new instance of MaintWorkflowStepAction */
  public MaintWorkflowStepAction() {
    super();
  }

  /** getFunctionCode
   *
   * Abstract function which sub-class should implement to return the corresponding
   * function code.
   *
   * @return   The function code
   */
  public String getFunctionCode() {
    return(SystemFunctionConstant.WORKFLOW_RECORD);
  }

  /** getMajorDAOClassName
   *
   * Abstract function which sub-class should implement to return the corresponding
   * major DAO class name used in this class.
   *
   * @return   The DAO class name
   */
  public String getMajorDAOClassName() {
    return("com.dcivision.workflow.dao.WorkflowStepDAObject");
  }

  public void clearUniqueFields(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    super.clearUniqueFields(mapping, form, request, response);
    MaintWorkflowStepForm workflowStepForm = (MaintWorkflowStepForm) form;
    workflowStepForm.setID(null);
    workflowStepForm.setStepSeq(null);
    workflowStepForm.setStepName(null);
    workflowStepForm.setActionType(null);
    workflowStepForm.setActionID(null);
    workflowStepForm.setDescription(null);
  }

  public void copyRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    super.copyRecord(mapping, form, request, response);
  }

  public void updateRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    WorkflowOperationManager operationManager = new WorkflowOperationManager(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStepManager stepManager=new WorkflowStepManager(this.getSessionContainer(request), this.getConnection(request));
    MaintWorkflowStepForm stepForm = (MaintWorkflowStepForm) form;
    WorkflowStep step = (WorkflowStep) form.getFormData();
    // if the step action type is ACTION_TYPE_USER_DEFINED_TASK,
    // then update the routine Worklow_Step_Routine table for this step
    if(WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK.equals(step.getActionType())  ) {
    	stepManager.deleteStepRouteByStepID(step.getID());
      this.insertWorkflowStepRoutine(request,step.getID());

    //  if the step action type is ACTION_TYPE_FORM_DRIVEN,
    // then update the form equation Worklow_Step_Form_Equation table for this step
    } else if(WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(step.getActionType())  ) {
      stepManager.deleteStepFormEquatByStepID(step.getID());
      this.insertWorkflowStepFormEquat(request,step.getID());
      //added by nancy
    }else if(WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(step.getActionType().substring(0,1))  ) {
    	stepManager.deleteStepParametersByStepID(step.getID());
    	this.insertWorkflowStepParameter(request,step.getID());
    }
    //end


   // Add By Dick
   // update the notification rule for this step notification
    stepManager.deleteStepNotificationRuleByStepID(step.getID());
    this.insertWorkflowStepNotificationRule(request, form, step.getID());

    stepManager.deleteStepPriorityRuleByStepID(step.getID());
    this.insertWorkflowStepPriorityRule(request, form, step.getID());
   /*
    if(!Utility.isEmpty(stepForm.getCategoryID()) && step.getStepSeq().intValue() == 1 && this.WORKFLOW_CATEGORY_ID_INTERRUPT.equals(stepForm.getCategoryID())) {
      this.insertWorkflowStepOwnerInToInterruptUserActor(request, step);
    }
    */
    
    //process the bind form item
    stepManager.deleteStepFormRecordByStepID(step.getID());
    this.insertBindForm(step.getID(), form, request);
    

    //insert property resource record
    this.deleteProtectedResourceInfo(request, step.getID());
    this.insertProtectedResourceInfo(request, form, step);

    step = operationManager.updateWorkflowStep(step);

    //update the workflow stage
    this.updateWorkflowStage(request, form, step.getID());
    //update workflow record update_info
    this.updateWorkflowRecord(request, step.getWorkflowRecordID());
  }

  public void deleteRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    WorkflowOperationManager operationManager = new WorkflowOperationManager(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStepManager stepManager=new WorkflowStepManager(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStep step = (WorkflowStep) form.getFormData();

    // if the step action type is ACTION_TYPE_USER_DEFINED_TASK,
    // then delete the routine from Worklow_Step_Routine table for this step
    if(WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK.equals(step.getActionType())  ) {
      stepManager.deleteStepRouteByStepID(step.getID());
    	
    // if the step action type is ACTION_TYPE_FORM_DRIVEN,
    // then delete the form equation from Worklow_Step_Form_Equat table for this step
    } else if(WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(step.getActionType()) ){
    	stepManager.deleteStepFormEquatByStepID(step.getID());
      //added by nancy
    }else if(WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(step.getActionType().substring(0,1))  ) {
    	stepManager.deleteStepParametersByStepID(step.getID());
    }
    //end

    //delete bind form items
    stepManager.deleteStepFormRecordByStepID(step.getID());
    operationManager.deleteSingleWorkflowStep(step.getID());
    //update workflow reocrd update_info
    this.updateWorkflowRecord(request, step.getWorkflowRecordID());
  }

  public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws ServletException {
    ActionForward retValue;
    AbstractActionForm maintForm = (AbstractActionForm)form;
    MaintWorkflowStepForm stepForm = (MaintWorkflowStepForm) maintForm;
    String opMode = maintForm.getOpMode();
    String navMode = maintForm.getNavMode();
    String operationType = request.getParameter("operationType");
    String categoryID = request.getParameter("categoryID");
    stepForm.setCategoryID(categoryID);
    //get the working calendar list.
    this.getWorkingCalendarList(request);
    //get the stage list
    this.getStageArray(request, form);
    
    // Set the function code for current action.
    ActionForward forward = this.retrieveFunctionCode(request, response, mapping);  if (forward!=null) {return forward;}
    try {
      //Added By Dick
      String workflowRecordID = request.getParameter("workflowRecordID");
      String parentStepID = request.getParameter("parentStepID");
      Locale locale = this.getSessionContainer(request).getSessionLocale();
      WorkflowRetrievalManager retrievalManager = new WorkflowRetrievalManager(this.getSessionContainer(request), this.getConnection(request));
      List parentStepNameList = new ArrayList();
      if (!Utility.isEmpty(parentStepID)) {
        parentStepNameList = retrievalManager.getSuperStepNameListByWorkflowStepID(new Integer(parentStepID));
      }
      String[][] ACTOR_TYPE_MAP = new String[parentStepNameList.size() + 5][2];      
      ACTOR_TYPE_MAP[0][0] = MessageResourcesFactory.getMessage(locale, "workflow.label.everyone");
      ACTOR_TYPE_MAP[0][1] = MtmWorkflowStepUserActor.ACTOR_TYPE_EVERYONE;

      ACTOR_TYPE_MAP[1][0] = MessageResourcesFactory.getMessage(locale, "workflow.label.submitter");
      ACTOR_TYPE_MAP[1][1] = MtmWorkflowStepUserActor.ACTOR_TYPE_SUBMITTER;

      ACTOR_TYPE_MAP[2][0] = MessageResourcesFactory.getMessage(locale, "workflow.label.report_to");
      ACTOR_TYPE_MAP[2][1] = MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO;
//      ACTOR_TYPE_MAP[2][0] = MessageResourcesFactory.getMessage(locale, "workflow.label.previous_task_owner");
//      ACTOR_TYPE_MAP[2][1] = MtmWorkflowStepUserActor.ACTOR_TYPE_PREVIOUS_TASK_OWNER;

      ACTOR_TYPE_MAP[3][0] = MessageResourcesFactory.getMessage(locale, "workflow.label.previous_task_action_taker");
      ACTOR_TYPE_MAP[3][1] = MtmWorkflowStepUserActor.ACTOR_TYPE_PREVIOUS_TASK_ACTION_TAKER;
      ACTOR_TYPE_MAP[4][0] = MessageResourcesFactory.getMessage(locale, "workflow.label.report_to_of_previous_task");
      ACTOR_TYPE_MAP[4][1] = MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_PREVIOUS_TASK_ACTION_TAKER;
      for ( int i = 0; i < parentStepNameList.size(); i++ ) {
        String[] stepName = (String[])parentStepNameList.get(i);
        ACTOR_TYPE_MAP[i + 5][0] = stepName[1];
        ACTOR_TYPE_MAP[i + 5][1] = stepName[0];
      }
      request.setAttribute("ACTOR_TYPE_MAP",ACTOR_TYPE_MAP);

      //End
      if(WorkflowStep.OPERATION_TYPE_DELETE_SINGLE_STEP.equals(operationType)){
        String currentWorkflowStepID = request.getParameter("currentWorkflowStepID");
        String workflowGroupID = request.getParameter("workflowGroupID");
        String parentType = request.getParameter("parentType");

        this.retrieveMoveStepInfo(maintForm,request,new Integer(currentWorkflowStepID), new Integer(parentStepID));
        retrieveDeleteStepAllChildStep((AbstractActionForm)form, request);
        return mapping.findForward(WorkflowStep.NAV_MODE_MOV);

      }
      //Move Single Step or Move All Step After. MS = Move Single, MA = Move All
      if(WorkflowStep.OPERATION_TYPE_MOVE_SINGLE_STEP.equals(operationType) ||
            WorkflowStep.OPERATION_TYPE_MOVE_ALL_STEP_AFTER.equals(operationType)){
        String currentWorkflowStepID = request.getParameter("currentWorkflowStepID");
        String workflowGroupID = request.getParameter("workflowGroupID");
        String parentType = request.getParameter("parentType");
        String currentStepActionType = request.getParameter("currentStepActionType");
        String dropOption = parentType + "-" + parentStepID;
        
        if(WorkflowStep.ACTION_TYPE_APPROVAL.equals(currentStepActionType) ){
          dropOption += WorkflowStep.PARENT_TYPE_APPROVED + "-" + currentWorkflowStepID;
          dropOption += WorkflowStep.PARENT_TYPE_REJECTED + "-" + currentWorkflowStepID;
                   
        } else if (WorkflowStep.ACTION_TYPE_BOOLEAN.equals(currentStepActionType) ) {
          dropOption += WorkflowStep.PARENT_TYPE_YES + "-" + currentWorkflowStepID;
          dropOption += WorkflowStep.PARENT_TYPE_NO + "-" + currentWorkflowStepID;  
                 
        } else if (WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(currentStepActionType) ) {
          dropOption += WorkflowStep.PARENT_TYPE_FROM_VALUE_DRIVEN + "-" + currentWorkflowStepID;
        
        } else if (WorkflowStep.ACTION_TYPE_TASK_TO_DO.equals(currentStepActionType) ) {
          dropOption += WorkflowStep.PARENT_TYPE_SINGLE + "-" + currentWorkflowStepID;
        } 

        this.retrieveMoveStepInfo(maintForm,request,new Integer(currentWorkflowStepID), new Integer(parentStepID));
        retrieveParentWorkflowStepArray((AbstractActionForm)form, request);
        String[][] workflowStepMoveList = (String[][])request.getAttribute("workflowStepParentList");
        List currentList = new ArrayList();
        for(int i=0; i<workflowStepMoveList.length; i++){            
          if(dropOption.indexOf(workflowStepMoveList[i][1]) < 0 && 
             !(WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK.equals(currentStepActionType) && workflowStepMoveList[i][1].indexOf("-" + currentWorkflowStepID) > 0   ) ){
            currentList.add(workflowStepMoveList[i]);
         }
        }
        String[][] aParentStep = new String[currentList.size()][];
        for (int i=0; i<currentList.size(); i++) {
          aParentStep[i] = (String[]) currentList.get(i);
        }
        log.debug("this parentStep list is >>> " + currentList.size());
        if (Utility.isEmpty(currentList)) {
          log.debug("this parentStep list is >>> " + currentList.size());
          addError(request, WORKFLOW_STEP_ERROR_NO_FOUND_STEPS);
        }
        request.setAttribute(WORKFLOW_STEP_PARENT_LIST, aParentStep);
        if(WorkflowStep.OPERATION_TYPE_MOVE_SINGLE_STEP.equals(operationType)){
          if (!Utility.isEmpty(currentWorkflowStepID)) {
            List nextStepsList = this.getNextStepByCurrentStepID(new Integer(currentWorkflowStepID), request);
            request.setAttribute("nextStepsList", nextStepsList);
          } else {
            log.debug("Error:   have not current step ID");
          }
          stepForm.setOptions(GlobalConstant.FALSE);
        } else {
          stepForm.setOptions(GlobalConstant.TRUE);
        }
        request.setAttribute("operationType",operationType);
        return mapping.findForward(WorkflowStep.NAV_MODE_MOV);
      }
      retrieveWorkflowStepTypes((AbstractActionForm)form, request);
      retrieveParentWorkflowStepArray((AbstractActionForm)form, request);
      if (WorkflowStep.OP_MODE_MOV.equals(opMode) && WorkflowStep.NAV_MODE_MOV.equals(navMode)){
        try {
          this.moveWorkflowStep(mapping, maintForm, request, response);
          this.handleWorkflowRoutine(mapping, maintForm, request, response, opMode, navMode);
          this.commit(request);
          form.reset(mapping, request);
          this.init(mapping, maintForm, request, response);
          addMessage(request, MESSAGE_RECORD_UPDATE);
        } catch (ApplicationException appEx) {
          this.rollback(request);
          handleApplicationException(request, appEx);
        }
        if (isError(request)) {
          maintForm.setNavMode(GlobalConstant.NAV_MODE_NEW);
          return mapping.findForward(WorkflowStep.NAV_MODE_MOV);
        } else {
          maintForm.setNavMode(WorkflowStep.OPERATION_TYPE_MOVE_SINGLE_STEP);
          return mapping.findForward(WorkflowStep.NAV_MODE_MOV);
        }
      }

      if (Utility.isEmpty(opMode)) {

        if (Utility.isEmpty(navMode) || GlobalConstant.NAV_MODE_NEW.equals(navMode)) {
          //WorkflowRetrievalManager retrievalManager = new WorkflowRetrievalManager(this.getSessionContainer(request), this.getConnection(request));
          MtmWorkflowStepWorkflowStepDAObject stepStepDAO = (MtmWorkflowStepWorkflowStepDAObject) this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.MtmWorkflowStepWorkflowStepDAObject");
          // New navigation.
          this.init(mapping, maintForm, request, response);
          maintForm.setNavMode(GlobalConstant.NAV_MODE_NEW);
         

          //* auto fill the step seq number

          Integer nextSeqNum = retrievalManager.getNextStepSeqNumber(TextUtility.parseIntegerObj(stepForm.getWorkflowRecordID()));
          stepForm.setStepSeq(TextUtility.formatIntegerObj(nextSeqNum));

       //log.debug("!!!!!!!!!!!!! file step list !!!!!!!!!!!");
          //* auto fill the parent step list
          if ("Y".equals(stepForm.getIsMerge())) {
            Integer groupID = TextUtility.parseIntegerObj(stepForm.getWorkflowGroupID());
            Integer recordID = TextUtility.parseIntegerObj(stepForm.getWorkflowRecordID());
            List sameGroupSteps = stepStepDAO.getListUnderSameGroupByWorkflowRecordIDAndGroupID(recordID, groupID);
            String[] parentIDs = new String[sameGroupSteps.size()];
            for (int i=0; i<sameGroupSteps.size(); i++) {
              MtmWorkflowStepWorkflowStep tmpStepStep = (MtmWorkflowStepWorkflowStep) sameGroupSteps.get(i);
              parentIDs[i] = tmpStepStep.getParentType() + "-" + tmpStepStep.getParentStepID().toString();
            }
          } else {
       //log.debug("!!!!!!!!!!!!! not merge case: "+stepForm.getParentStepID()+" !!!!!!!!!!!");
            String[] parentIDs = new String[1];
            parentIDs[0] = stepForm.getParentType() + "-" + stepForm.getParentStepID();
            stepForm.setParentStepIDs(parentIDs);
          }

          retValue =  mapping.findForward(GlobalConstant.NAV_MODE_NEW);
        } else {
          retValue = super.execute(mapping, form, request, response);
        }

      } else {
        if (GlobalConstant.NAV_MODE_REFRESH.equals(opMode)) {
          try {
         	 //added by nancy
          	stepForm.setParameterListValue(retrievalManager.getStringForParameter(null,stepForm.getActionType()));
      		if(Utility.isEmpty(stepForm.getStepSeq())){
          	Integer nextSeqNum = retrievalManager.getNextStepSeqNumber(TextUtility.parseIntegerObj(stepForm.getWorkflowRecordID()));
            stepForm.setStepSeq(TextUtility.formatIntegerObj(nextSeqNum));
      		}
//          end
            refreshFormData(mapping, maintForm, request, response);
          } catch (ApplicationException appEx) {
            this.rollback(request);
            handleApplicationException(request, appEx);
          }
          if (isError(request)) {
            maintForm.setNavMode(GlobalConstant.NAV_MODE_EDIT);
            retValue =  mapping.findForward(GlobalConstant.NAV_MODE_EDIT);
          } else {
            retValue = mapping.findForward(GlobalConstant.NAV_MODE_REFRESH);
          }
        } else {
          if(!Utility.isEmpty(parentStepID)){
            //bill add for EIP-1709 start
            WorkflowStepDAObject workflowStepDAO=new WorkflowStepDAObject(this.getSessionContainer(request),this.getConnection(request));
            //get parent step of this current step
            WorkflowStep parentStep=(WorkflowStep)workflowStepDAO.getStepByID(new Integer(parentStepID));
            MtmWorkflowStepUserActorDAObject stepUserDAO=new MtmWorkflowStepUserActorDAObject(this.getSessionContainer(request),this.getConnection(request));
            //get user actor list of parent step
            List parentStepUserActorList=stepUserDAO.getListByWorkflowStepID(parentStep.getID());
            boolean isPreviousTaskActionTaker=false;
            String allPermissionData=request.getParameter("allPermissionData");
            String[] allPermissionDataArray=allPermissionData.split("\n");
            for(int index=0;index<allPermissionDataArray.length;index++){
              String [] onePermissionDataArray=allPermissionDataArray[index].split("\t");
              //onePermissionDataArray[0] is actor type
              if(MtmWorkflowStepUserActor.ACTOR_TYPE_PREVIOUS_TASK_ACTION_TAKER.equals(onePermissionDataArray[0])){
                isPreviousTaskActionTaker=true;
              }
            }
            //Previous Task Action Taker's Supervisor is not allowed after automatic task step.
            if(Utility.isEmpty(parentStepUserActorList)&& isPreviousTaskActionTaker){
              maintForm.setNavMode(GlobalConstant.NAV_MODE_EDIT);
              this.addError(request, "errors.workflow.report_to_is_not_allowed_after_automatic_task",parentStep.getStepName());
              return mapping.findForward(GlobalConstant.NAV_MODE_EDIT);
            }
            //bill add for EIP-1709 end
          }
          retValue = super.execute(mapping, form, request, response);
        }
      }

      return retValue;
    } catch (ApplicationException ex) {
      handleApplicationException(request, ex);
      return mapping.findForward(GlobalConstant.NAV_MODE_LIST);
    }
  }


  public void insertRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    WorkflowOperationManager operationManager = new WorkflowOperationManager(this.getSessionContainer(request), this.getConnection(request));
    //MtmWorkflowStepWorkflowStepDAObject stepStepDAO =  (MtmWorkflowStepWorkflowStepDAObject) this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.MtmWorkflowStepWorkflowStepDAObject");
    //MtmWorkflowStepUserActorDAObject stepActorDAO = (MtmWorkflowStepUserActorDAObject) this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.MtmWorkflowStepUserActorDAObject");

    MaintWorkflowStepForm maintForm = (MaintWorkflowStepForm)form;
    WorkflowStep step = (WorkflowStep) (maintForm.getFormData());

    if ( WorkflowStep.INSERT_LOOPBACK_STEP.equals(((MaintWorkflowStepForm)form).getInsertStepType()) ) {
      operationManager.createLoopBackWorkflowStep(step);
    } else if (WorkflowStep.INSERT_END_STEP.equals(((MaintWorkflowStepForm)form).getInsertStepType()) ) {
      operationManager.insertEndStepLinkAfterStep(step);
    } else {
        String operationType = request.getParameter("operationType");
        //create step according to step type
        if(!WorkflowStep.OPERATION_TYPE_INSERT_BETWEEN.equals(operationType)){
          step = operationManager.createWorkflowStep(step,false);//insert a general step
        } else {
          if(Utility.isEmpty(step.getParentStepIDs())){
            step.setParentStepIDs(new String[]{step.getParentType()+"-"+step.getParentStepID()});
          }
          step = operationManager.createWorkflowStep(step,true);//insert a step between
        }
    }

    // if the step action type is ACTION_TYPE_USER_DEFINED_TASK,
    // then insert the routine into Worklow_Step_Routine table for this step
    if(WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK.equals(step.getActionType())  ) {
      this.insertWorkflowStepRoutine(request,step.getID());

    // if the step action type is ACTION_TYPE_FORM_DRIVEN,
    // then insert the form equation into Workflow_Step_Form_Equat table for this step
    } else if(WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(step.getActionType()) ){
      this.insertWorkflowStepFormEquat(request,step.getID());
      
      //added by nancy
    }else if(WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(step.getActionType())  ) {
    	this.insertWorkflowStepParameter(request,step.getID());
    }
    //end
    
    // setup the priority rule for this step priority.
    this.insertWorkflowStepPriorityRule(request, form, step.getID());

    //setup the notification rules for this step notification.
    this.insertWorkflowStepNotificationRule(request,form,step.getID());

    //insert property resource record
    if(GlobalConstant.TRUE.equals(maintForm.getProtectedStep())) {
      this.insertProtectedResourceInfo(request, form, step);
    }
 
    //process bind form
    if(!Utility.isEmpty(step.getID()))//TC.ADD FOR BUG 899
    this.insertBindForm(step.getID(), form, request);

    //insert workflow stage
    this.insertWorkflowStage(request, form, step.getID()); 
    
    //update workflow record update info
    this.updateWorkflowRecord(request,step.getWorkflowRecordID());
  }

  /**
   * Move a single step or move all steps after the current step and the current step
   * @param mapping
   * @param form
   * @param request
   * @param response
   * @throws ApplicationException
   */
  public void moveWorkflowStep(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    WorkflowOperationManager operationManager = new WorkflowOperationManager(this.getSessionContainer(request), this.getConnection(request));
    MtmWorkflowStepWorkflowStepDAObject stepStepDAO =  (MtmWorkflowStepWorkflowStepDAObject) this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.MtmWorkflowStepWorkflowStepDAObject");
    MtmWorkflowStepUserActorDAObject stepActorDAO = (MtmWorkflowStepUserActorDAObject) this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.MtmWorkflowStepUserActorDAObject");

    MaintWorkflowStepForm maintForm = (MaintWorkflowStepForm)form;
    WorkflowStep step = (WorkflowStep) (maintForm.getFormData());
    String[] moveToStep = maintForm.getMoveToStepID().split("-");
    String[] connectStep= maintForm.getConnectStepID().split("-");
    if (maintForm.getOptions()!=null){
      //operationManager.moveWorkflowStepsTree(step,TextUtility.parseIntegerObj(moveToStep[1]), moveToStep[0],TextUtility.parseIntegerObj(maintForm.getParentStepID()),true);
      operationManager.moveWorkflowStepsTree(step,TextUtility.parseIntegerObj(connectStep[1]),connectStep[0],TextUtility.parseIntegerObj(moveToStep[1]),moveToStep[0],TextUtility.parseIntegerObj(maintForm.getParentStepID()),maintForm.getParentType(),true,maintForm.getOperateType());
    } else {
      //operationManager.moveWorkflowStepsTree(step,TextUtility.parseIntegerObj(moveToStep[1]), moveToStep[0],TextUtility.parseIntegerObj(maintForm.getParentStepID()),false);
      operationManager.moveWorkflowStepsTree(step,TextUtility.parseIntegerObj(connectStep[1]),connectStep[0],TextUtility.parseIntegerObj(moveToStep[1]),moveToStep[0],TextUtility.parseIntegerObj(maintForm.getParentStepID()),maintForm.getParentType(),false,maintForm.getOperateType());
    }
    //this.commit(request);
    updateWorkflowRecord(request,step.getWorkflowRecordID());
  }

  public void selectRecord(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    WorkflowRetrievalManager retrievalManager = new WorkflowRetrievalManager(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStepOperationWarningMessageManager messageManager = new WorkflowStepOperationWarningMessageManager(this.getSessionContainer(request),this.getConnection(request));
    
    WorkflowRecordDAObject recordDAO = new WorkflowRecordDAObject(this.getSessionContainer(request), this.getConnection(request));
    WorkflowRecord wfRecord = (WorkflowRecord) recordDAO.getObjectByID(TextUtility.parseIntegerObj(((MaintWorkflowStepForm)form).getWorkflowRecordID() ));
    MaintWorkflowStepForm workflowStepForm = (MaintWorkflowStepForm)form;
    String categoryIDStr = workflowStepForm.getCategoryID();
    request.setAttribute("workflowRecord", wfRecord);
    Integer ID = TextUtility.parseIntegerObj(form.getID());
    Integer groupID = TextUtility.parseIntegerObj(((MaintWorkflowStepForm)form).getGroupID());
    AbstractBaseObject data = retrievalManager.getWorkflowStepInfo(ID, groupID);
    form.setFormData(data);
   	//added by nancy
    workflowStepForm.setParameterListValue(retrievalManager.getStringForParameter(ID,null));
    //end
    this.getProtectedResourceInfo(request, form, ID);
    //add by greatwall for eip112 
    this.getParamValue(request, form, ID);
    //end    
    workflowStepForm.setCategoryID(categoryIDStr);
    this.addMessages(request, messageManager.createWorkflowStepWarningMessage((WorkflowStep)data,GlobalConstant.OP_MODE_UPDATE));
  }
/**
 * add by greatwall for eip112 
 * @param request
 * @param form
 * @param ID
 * @throws ApplicationException
 */
  private void getParamValue(HttpServletRequest request, AbstractActionForm form, Integer ID)
      throws ApplicationException {
    MaintWorkflowStepForm workflowStepForm = (MaintWorkflowStepForm) form;
    WorkflowStepParameterValueDAObject stepParamValueDAO = new WorkflowStepParameterValueDAObject(this
        .getSessionContainer(request), this.getConnection(request));
    List stepParamValueList = stepParamValueDAO.getListByStepID(ID);
    WorkflowStepParameterValue tmpWorkflowStepParameterValue = null;
    for (int i = 0; i < stepParamValueList.size(); i++) {
      tmpWorkflowStepParameterValue = (WorkflowStepParameterValue) stepParamValueList.get(i);
      if (WorkflowRetrievalManager.PARAMVALUE_AUTOTASK.equals(tmpWorkflowStepParameterValue.getParameterType())) {
        int delay = TextUtility.parseInteger(tmpWorkflowStepParameterValue.getParameterName());
        if (delay > 0) {
          workflowStepForm.setDelay(tmpWorkflowStepParameterValue.getParameterName());          
        }
        workflowStepForm.setAutoTaskType(tmpWorkflowStepParameterValue.getParameterValue());
      }
    }
  }

  public void refreshFormData(ActionMapping mapping, AbstractActionForm form, HttpServletRequest request, HttpServletResponse  response) throws ApplicationException {
    MaintWorkflowStepForm stepForm = (MaintWorkflowStepForm) form;
    
    //================= To hold the permission value begin ====================
    //To hold the permission value
    List actorTypeList = new ArrayList();
    String permData = TextUtility.replaceString(stepForm.getAllPermissionData(), "\r", "");
    String[] tmpAry = TextUtility.splitString(permData, "\n");
    if (tmpAry == null) {
      tmpAry = new String[0];
    }
    
    for (int i = 0; i < tmpAry.length; i++) {
      if (!Utility.isEmpty(tmpAry[i])) {
        String[] rowAry = TextUtility.splitString(tmpAry[i], "\t");
        MtmWorkflowStepUserActor mtmWorkflowStepUserActor = new MtmWorkflowStepUserActor();
        
        if (MtmWorkflowStepUserActor.ACTOR_TYPE_GROUP.equals(rowAry[2]) || MtmWorkflowStepUserActor.ACTOR_TYPE_ROLE.equals(rowAry[2]) || MtmWorkflowStepUserActor.ACTOR_TYPE_USER.equals(rowAry[2])){
          mtmWorkflowStepUserActor.setActorType(rowAry[2]);
          mtmWorkflowStepUserActor.setActorID(TextUtility.parseIntegerObj(rowAry[0]));
        } else {
          mtmWorkflowStepUserActor.setActorType(rowAry[0].substring(0,1));
          if(MtmWorkflowStepUserActor.ACTOR_TYPE_ACTION_TAKER.equals(rowAry[0].substring(0,1)) ||
            MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_ACTION_TAKER.equals(rowAry[0].substring(0,1))){
            mtmWorkflowStepUserActor.setActorID( new Integer(rowAry[0].substring(1)));
          }else{
            mtmWorkflowStepUserActor.setActorID(new Integer(0));
          }
        }
        mtmWorkflowStepUserActor.setPermission(rowAry[3]);

        if (MtmWorkflowStepUserActor.ACTOR_TYPE_SUBMITTER.equals(mtmWorkflowStepUserActor.getActorType())
        		|| MtmWorkflowStepUserActor.ACTOR_TYPE_EVERYONE.equals(mtmWorkflowStepUserActor.getActorType())
						|| MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO.equals(mtmWorkflowStepUserActor.getActorType())
						|| MtmWorkflowStepUserActor.ACTOR_TYPE_RECURSIVE_RUNTIME_ASSIGN.equals(mtmWorkflowStepUserActor.getActorType())
						|| MtmWorkflowStepUserActor.ACTOR_TYPE_PREVIOUS_TASK_OWNER.equals(mtmWorkflowStepUserActor.getActorType())
						|| MtmWorkflowStepUserActor.ACTOR_TYPE_PREVIOUS_TASK_ACTION_TAKER.equals(mtmWorkflowStepUserActor.getActorType())                                 
						|| MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_PREVIOUS_TASK_ACTION_TAKER.equals(mtmWorkflowStepUserActor.getActorType())
						|| MtmWorkflowStepUserActor.ACTOR_TYPE_ACTION_TAKER.equals(mtmWorkflowStepUserActor.getActorType()) 
						|| MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_ACTION_TAKER.equals(mtmWorkflowStepUserActor.getActorType())                                 
         )  {
        	if( MtmWorkflowStepUserActor.ACTOR_TYPE_ACTION_TAKER.equals(mtmWorkflowStepUserActor.getActorType()) 
        			|| MtmWorkflowStepUserActor.ACTOR_TYPE_REPORT_TO_OF_ACTION_TAKER.equals(mtmWorkflowStepUserActor.getActorType()) ){
        		actorTypeList.add(mtmWorkflowStepUserActor.getActorType() + mtmWorkflowStepUserActor.getActorID() + "_" + mtmWorkflowStepUserActor.getPermission());
        	} else {
        		actorTypeList.add(mtmWorkflowStepUserActor.getActorType() + "_" + mtmWorkflowStepUserActor.getPermission());         
        	}
        } else {
          actorTypeList.add(mtmWorkflowStepUserActor.getActorType() + mtmWorkflowStepUserActor.getActorID() + "_" + mtmWorkflowStepUserActor.getPermission());
        }  
      }
    }
    String[] actorTypes = new String[0];    
    actorTypes = (String[]) actorTypeList.toArray(actorTypes);
    stepForm.setActorTypes(actorTypes);
    //================== To hold the permission value end  ====================
    
    if (WorkflowStep.INSERT_LOOPBACK_STEP.equals(stepForm.getInsertStepType()) && !Utility.isEmpty(stepForm.getLoopBackStepID())) {
      if (this.checkObjectStepIsSuperStep(TextUtility.parseIntegerObj(stepForm.getLoopBackStepID()), TextUtility.parseIntegerObj(stepForm.getCurrentStepID()), request)) {
        if (this.checkHaveCollocateSteps(TextUtility.parseIntegerObj(stepForm.getLoopBackStepID()), request)) {
          stepForm.setHaveColloCantSteps(true);
        }
      }
    }
  }

  private void retrieveWorkflowStepTypes(AbstractActionForm form, HttpServletRequest request) throws ApplicationException {
    /*List workflowStepTypesList = new ArrayList();
    workflowStepTypesList.add(new String[]{"workflow.label.step_type_A", WorkflowStep.ACTION_TYPE_APPROVAL});//Approval Task
    workflowStepTypesList.add(new String[]{"workflow.label.step_type_T", WorkflowStep.ACTION_TYPE_TASK_TO_DO});//To Do Task
    workflowStepTypesList.add(new String[]{"workflow.label.step_type_B", WorkflowStep.ACTION_TYPE_BOOLEAN});//Yes/No Task
    workflowStepTypesList.add(new String[]{"workflow.label.step_type_U", WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK});//User Defined Task
    SessionContainer sessionContainer = (SessionContainer) request.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);
    try{
      MaintWorkflowStepForm maintForm = (MaintWorkflowStepForm) form;
      WorkflowRecordDAObject workflowRecordDAO = (WorkflowRecordDAObject) this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.WorkflowRecordDAObject");
      WorkflowActionDAObject workflowActionDAO = (WorkflowActionDAObject) this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.WorkflowActionDAObject");

      //WorkflowRecord workflowRecord = (WorkflowRecord)workflowRecordDAO.getObjectByID(TextUtility.parseIntegerObj(maintForm.getWorkflowRecordID()));//simon_del


      //check if the workflow category of the workflow record is ParaForm related.
      //if(SystemWorkflowConstant.FMB_SUBMISSION_BY_FORM.equals(workflowRecord.getWorkflowCategoryID().toString() )){//simon_del
      if(!Utility.isEmpty(maintForm.getCategoryID())) {   // falcon_add EIP-216
        if(SystemWorkflowConstant.FMB_SUBMISSION_BY_FORM.equals(maintForm.getCategoryID().toString() )){//simon_add
          workflowStepTypesList.add(new String[]{"workflow.label.step_type_F", WorkflowStep.ACTION_TYPE_FORM_DRIVEN});//Form Value Driven Task
        }
      }

      workflowStepTypesList.add(new String[]{"workflow.label.type_separator", ""});

      //List workflowActionList = workflowActionDAO.getListByWorkflowCategoryID(workflowRecord.getWorkflowCategoryID());//simon_del
      List workflowActionList = workflowActionDAO.getListByWorkflowCategoryID(TextUtility.parseIntegerObj(maintForm.getCategoryID()));//simon_add
      for (int i=0; i< workflowActionList.size(); i++) {
        WorkflowAction workflowAction = (WorkflowAction) workflowActionList.get(i);
        //sliever.hu.add
        if(!workflowAction.getActionClassName().equals("com.dcivision.workflow.action.AutoRollbackPreStep")){
        workflowStepTypesList.add(new String[]{workflowAction.getActionLabel(), WorkflowStep.ACTION_TYPE_SYSTEM_AUTO + workflowAction.getID().toString()});
        }
      }
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_UNKNOWN_DAO, e);
    } finally {

      String[][] aWorkflowStepTypes = new String[workflowStepTypesList.size()+1][];
      aWorkflowStepTypes[0]=new String[]{MessageResourcesFactory.getMessage(sessionContainer.getSessionLocale(), "common.options.select_menu.select_one"), ""};
      for (int i=1; i<=workflowStepTypesList.size(); i++) {
        String [] types = (String[]) workflowStepTypesList.get(i-1);
        types[0]=getLableMessage(sessionContainer, types[0]);
        aWorkflowStepTypes[i]=types;
      }
      request.setAttribute(WORKFLOW_STEP_TYPES, aWorkflowStepTypes);
    }*/
    MaintWorkflowStepForm maintForm = (MaintWorkflowStepForm) form;
    SessionContainer sessionContainer = this.getSessionContainer(request);
    Connection conn = this.getConnection(request);
    WorkflowStepManager stepManager = new WorkflowStepManager(sessionContainer,conn);
    String[][] aWorkflowStepTypes = stepManager.retrieveWorkflowStepTypes(maintForm.getCategoryID());//
    request.setAttribute(WORKFLOW_STEP_TYPES, aWorkflowStepTypes);
  }

  /*private String getLableMessage(SessionContainer sessionContainer, String lable) throws NumberFormatException {
    String lableMessage ="";
    lableMessage=MessageResourcesFactory.getMessage(sessionContainer.getSessionLocale(), lable);
    if(lableMessage.matches("\\?\\?\\?.+\\?\\?\\?"))//Struts1.1.org.apache.struts.util.PropertyMessageResources.getMessage:"???" + messageKey(locale, key) + "???"
      lableMessage = lable;
    return lableMessage;
  }*/

  private void retrieveParentWorkflowStepArray(AbstractActionForm form, HttpServletRequest request) throws ApplicationException {
    List parentStepList = new ArrayList();
    try{
      SessionContainer sessionContainer = (SessionContainer) request.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);
      Locale locale = sessionContainer.getSessionLocale();
      WorkflowRetrievalManager retrievalManager = new WorkflowRetrievalManager(sessionContainer, this.getConnection(request));
      MtmWorkflowStepWorkflowStepDAObject stepStepDAO = (MtmWorkflowStepWorkflowStepDAObject)this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.MtmWorkflowStepWorkflowStepDAObject");
      WorkflowStepDAObject stepDAO = (WorkflowStepDAObject)this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.WorkflowStepDAObject");
      String operationType = request.getParameter("operationType");
      MaintWorkflowStepForm maintForm = (MaintWorkflowStepForm) form;
      WorkflowStep workflowStep = (WorkflowStep) maintForm.getFormData();

      //get the current step's parent type from Mtm_WF_Step_WF_Step table
      if(!Utility.isEmpty(request.getParameter("currentWorkflowStepID"))){
        List tmpWfStep2List = stepStepDAO.getListByParentStepID(new Integer(request.getParameter("currentWorkflowStepID")) );
        for(int k=0; k<tmpWfStep2List.size(); k++){
          MtmWorkflowStepWorkflowStep mtmWfStep2 = (MtmWorkflowStepWorkflowStep)tmpWfStep2List.get(k);
          maintForm.setCurrentType(mtmWfStep2.getParentType());
          break;
        }
      }
      List workflowStepList = new ArrayList();
      if(WorkflowStep.OPERATION_TYPE_INSERT_BETWEEN.equals(operationType)) {
        workflowStepList = retrievalManager.getWorkflowStepListByRecordIDAndExcludeStep(workflowStep.getWorkflowRecordID(), null);
      } else {
        workflowStepList = retrievalManager.getWorkflowStepListByRecordIDAndExcludeStep(workflowStep.getWorkflowRecordID(), workflowStep.getCurrentStepID());
      }
      
      if (!Utility.isEmpty(workflowStep.getID()) ) {
      	WorkflowStep tmpWorkflowStep = (WorkflowStep)stepDAO.getObjectByID(workflowStep.getID());
      	if(WorkflowStep.ACTION_TYPE_END.equals(tmpWorkflowStep.getActionType()) ){
      		workflowStepList = stepDAO.getDistinctParentStepListByChildStepID(workflowStep.getID());
      	} 
      }
      
      //WorkflowStepDAObject workflowStepDAO = (WorkflowStepDAObject) this.getMajorDAObject(request);
      //List workflowStepList = workflowStepDAO.getListByWorkflowRecordID(TextUtility.parseIntegerObj(maintForm.getWorkflowRecordID()));
      for (int i=0; i<workflowStepList.size(); i++) {
        WorkflowStep tmpStep = (WorkflowStep) workflowStepList.get(i);
        String actionType = tmpStep.getActionType();

        if (WorkflowStep.ACTION_TYPE_SUBMIT.equals(actionType)) {
          String[] aOption = new String[2];
          aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName() + "[" + MessageResourcesFactory.getMessage(locale, "workflow.label.step_status_S") + "]";
          aOption[1] = WorkflowStep.PARENT_TYPE_SINGLE + "-" + tmpStep.getID();
          parentStepList.add(aOption);

        } else {

          MtmWorkflowStepWorkflowStepDAObject mtmStep= new MtmWorkflowStepWorkflowStepDAObject(sessionContainer, this.getConnection(request));
          if(Utility.isEmpty(mtmStep.getListByChildStepID(tmpStep.getID()))){
           continue;
          }
          
          if (WorkflowStep.ACTION_TYPE_APPROVAL.equals(actionType)) {
          String[] aOption = new String[2];
          aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName() + "[" + MessageResourcesFactory.getMessage(locale, "workflow.label.step_status_A") + "]";
          aOption[1] = WorkflowStep.PARENT_TYPE_APPROVED + "-" + tmpStep.getID();
          parentStepList.add(aOption);
          aOption = new String[2];
          aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName() + "[" + MessageResourcesFactory.getMessage(locale, "workflow.label.step_status_R") + "]";
          aOption[1] = WorkflowStep.PARENT_TYPE_REJECTED + "-" + tmpStep.getID();
          parentStepList.add(aOption);

        } else if (WorkflowStep.ACTION_TYPE_BOOLEAN.equals(actionType)) {
          String[] aOption = new String[2];
          aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName() + "[" + MessageResourcesFactory.getMessage(locale, "workflow.label.step_status_T") + "]";
          aOption[1] = WorkflowStep.PARENT_TYPE_YES + "-" + tmpStep.getID();
          parentStepList.add(aOption);
          aOption = new String[2];
          aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName() + "[" + MessageResourcesFactory.getMessage(locale, "workflow.label.step_status_F") + "]";
          aOption[1] = WorkflowStep.PARENT_TYPE_NO + "-" + tmpStep.getID();
          parentStepList.add(aOption);

        } else if (WorkflowStep.ACTION_TYPE_FORM_DRIVEN.equals(actionType)) {
          /*
          String[] aOption = new String[2];
          aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName() + "[" + MessageResourcesFactory.getMessage(locale, "workflow.label.step_status_D") + "]";
          aOption[1] = WorkflowStep.PARENT_TYPE_FROM_VALUE_DRIVEN + "-" + tmpStep.getID();
          parentStepList.add(aOption);
          */
          if(!Utility.isEmpty(tmpStep.getRouteListValue()) ){
            String[] routeArr = TextUtility.splitString(tmpStep.getRouteListValue(),"|");
            for(int j=0; j<routeArr.length; j++){
              String[] aOption = new String[2];
              aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName() + "[" + routeArr[j] + "]";//MessageResourcesFactory.getMessage(locale, "workflow.label.step_status_U")
              aOption[1] = WorkflowStep.PARENT_TYPE_SINGLE + j + "-" + tmpStep.getID();
              parentStepList.add(aOption);
            }
          }
        } else if (WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK.equals(actionType)) {
          if(!Utility.isEmpty(tmpStep.getRouteListValue()) ){
            String[] routeArr = TextUtility.splitString(tmpStep.getRouteListValue(),"|");
            for(int j=0; j<routeArr.length; j++){
              String[] aOption = new String[2];
              aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName() + "[" + routeArr[j] + "]";//MessageResourcesFactory.getMessage(locale, "workflow.label.step_status_U")
              aOption[1] = WorkflowStep.PARENT_TYPE_SINGLE + j + "-" + tmpStep.getID();
              parentStepList.add(aOption);
            }
          }

        } else if (WorkflowStep.ACTION_TYPE_TASK_TO_DO.equals(actionType)) {
          String[] aOption = new String[2];
          aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName() + "[" + MessageResourcesFactory.getMessage(locale, "workflow.label.step_status_G") + "]";
          aOption[1] = WorkflowStep.PARENT_TYPE_SINGLE + "-" + tmpStep.getID();
          parentStepList.add(aOption);

        } else if (WorkflowStep.ACTION_TYPE_SYSTEM_AUTO.equals(actionType)) {

          /***************************************************
           * TODO: handle different type of automatic task
           ***************************************************/
          WorkflowAction action = retrievalManager.getWorkflowActionByActionID(tmpStep.getActionID());
          WorkflowProcessor processor = AutomaticTaskFactory.getInstance(action);//Edit by TC for automaticTask Hotdeploy

          if (processor.getNumOfRoutine() == 1) {
            String[] aOption = new String[2];
            aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName() + "[" + MessageResourcesFactory.getMessage(locale, "workflow.label.step_status_G") + "]";
            aOption[1] = "S" + "-" + tmpStep.getID();
            parentStepList.add(aOption);
          } else {
            for(int j=0; j<processor.getNumOfRoutine(); j++) {
              String[] aOption = new String[2];
              aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName() + "[" + MessageResourcesFactory.getMessage(locale, processor.getLabelString(j)) + "]";
              aOption[1] = "S" + j + "-" + tmpStep.getID();
              parentStepList.add(aOption);
            }
          }
        } else if (WorkflowStep.ACTION_TYPE_END.equals(actionType)) {
          //SUBJECT TO CHANGE: now do nothing for the end node case, that means no step can be add after end step
        } else {
          throw new ApplicationException(WorkflowErrorConstant.UNKNOWN_WORKFLOW_ACTION_TYPE);
        }
      }
      }  
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_UNKNOWN_DAO, e);
    } finally {
      String[][] aParentStep = new String[parentStepList.size()][];
      for (int i=0; i<parentStepList.size(); i++) {
        aParentStep[i] = (String[]) parentStepList.get(i);
      }
      request.setAttribute(WORKFLOW_STEP_PARENT_LIST, aParentStep);

    }
  }

  private void retrieveDeleteStepAllChildStep(AbstractActionForm form, HttpServletRequest request) throws ApplicationException {
    List parentStepList = new ArrayList();
    try{
      SessionContainer sessionContainer = (SessionContainer) request.getSession().getAttribute(GlobalConstant.SESSION_CONTAINER_KEY);
      Locale locale = sessionContainer.getSessionLocale();
      WorkflowRetrievalManager retrievalManager = new WorkflowRetrievalManager(sessionContainer, this.getConnection(request));
      MtmWorkflowStepWorkflowStepDAObject stepStepDAO = (MtmWorkflowStepWorkflowStepDAObject)this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.MtmWorkflowStepWorkflowStepDAObject");
      WorkflowStepDAObject workflowStepDAObject = new WorkflowStepDAObject(this.getSessionContainer(request),this.getConnection(request));
      

      MaintWorkflowStepForm maintForm = (MaintWorkflowStepForm) form;
      WorkflowStep workflowStep = (WorkflowStep) maintForm.getFormData();

      //get the current step's parent type from Mtm_WF_Step_WF_Step table
      if(!Utility.isEmpty(request.getParameter("currentWorkflowStepID"))){
        List tmpWfStep2List = stepStepDAO.getListByParentStepID(new Integer(request.getParameter("currentWorkflowStepID")) );
        workflowStep = (WorkflowStep)workflowStepDAObject.getObjectByID(new Integer(request.getParameter("currentWorkflowStepID")));
        for(int k=0; k<tmpWfStep2List.size(); k++){
          MtmWorkflowStepWorkflowStep mtmWfStep2 = (MtmWorkflowStepWorkflowStep)tmpWfStep2List.get(k);
          maintForm.setCurrentType(mtmWfStep2.getParentType());
          break;
        }
      }

      List workflowStepList = retrievalManager.getChildWorkflowStepListByParentID(new Integer(request.getParameter("currentWorkflowStepID")));

      //WorkflowStepDAObject workflowStepDAO = (WorkflowStepDAObject) this.getMajorDAObject(request);
      //List workflowStepList = workflowStepDAO.getListByWorkflowRecordID(TextUtility.parseIntegerObj(maintForm.getWorkflowRecordID()));
      for (int i=0; i<workflowStepList.size(); i++) {
        WorkflowStep tmpStep = (WorkflowStep) workflowStepList.get(i);
        String actionType = workflowStep.getActionType();

         if (WorkflowStep.ACTION_TYPE_APPROVAL.equals(actionType)) {
          String[] aOption = new String[2];
          aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName();
          aOption[1] = tmpStep.getID().toString();
          parentStepList.add(aOption);
          } else if (WorkflowStep.ACTION_TYPE_BOOLEAN.equals(actionType)) {
          String[] aOption = new String[2];
          aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName();
          aOption[1] = tmpStep.getID().toString();
          parentStepList.add(aOption);

        } else if (WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK.equals(actionType)) {

          String[] aOption = new String[2];
          aOption[0] = tmpStep.getStepSeq() + ". " + tmpStep.getStepName();//MessageResourcesFactory.getMessage(locale, "workflow.label.step_status_U"
          aOption[1] = tmpStep.getID().toString();
          parentStepList.add(aOption);

        } else {
          throw new ApplicationException(WorkflowErrorConstant.UNKNOWN_WORKFLOW_ACTION_TYPE);
        }
      }

    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.COMMON_UNKNOWN_DAO, e);
    } finally {
      List currentStepList = new ArrayList();
      for (int i=0; i<parentStepList.size(); i++) {
        String flag = "N";
        String[] currentParentStep = (String[]) parentStepList.get(i);
        for (int j = 0; j < currentStepList.size(); j++ ){
          if (!Utility.isEmpty(currentStepList) && currentParentStep[1].equals(((String[])currentStepList.get(j))[1])) {
            flag = "Y";
            break; 
          }   
        }
        if ("N".equals(flag)){
          currentStepList.add(parentStepList.get(i));
        }  
      }
      String[][] aParentStep = new String[currentStepList.size()][];
      for (int i = 0; i < currentStepList.size(); i++) {
        aParentStep[i] = (String[])currentStepList.get(i);
      }
      request.setAttribute(WORKFLOW_STEP_PARENT_LIST, aParentStep);
    }

  }
//added by nancy
  /**
   * Insert paramets of this step into Workflow_Step_Parameter_Value
   * @param request
   * @param stepID
   * @throws ApplicationException
   */
  private void insertWorkflowStepParameter(
        HttpServletRequest request,
        Integer stepID) throws ApplicationException {
  	
  	WorkflowStepParameterValueDAObject wfStepParameterDAO = (WorkflowStepParameterValueDAObject) this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.WorkflowStepParameterValueDAObject");
    //  Insert route name into Workflow_Step_Route table
  	// add by greatwall for eip112
    String name = "-1" ;
    String value = "";
    if(!Utility.isEmpty(request.getParameter("autoTaskType"))&&"Sync".equals(request.getParameter("autoTaskType").trim()))
    {
      value = "Sync";
    }
    else{
      value = "aSync";
      if(!Utility.isEmpty(request.getParameter("delay")))
      {
        name = request.getParameter("delay");
      }
    }
    insertWorkflowStepParameter(stepID, wfStepParameterDAO, name, value, WorkflowRetrievalManager.PARAMVALUE_AUTOTASK);
    //end
    String  parametListValue = request.getParameter("parameterListValue");
  	log.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+parametListValue);
    if(!Utility.isEmpty(parametListValue) && !"null".equals(parametListValue) ){
      String[] parametArr = TextUtility.splitString(parametListValue,"|");
      for(int i=0; i<parametArr.length; i++){
         name = (TextUtility.splitString(parametArr[i],":"))[0];
         value = (TextUtility.splitString(parametArr[i],":"))[1];
      	insertWorkflowStepParameter(stepID, wfStepParameterDAO, name, value, WorkflowRetrievalManager.PARAMVALUE_SUB_WORKFLOW);
      }
    }
  }

  private void insertWorkflowStepParameter(Integer stepID, WorkflowStepParameterValueDAObject wfStepParameterDAO, String name, String value, String paramType) throws ApplicationException {
    WorkflowStepParameterValue tmpParamet = new WorkflowStepParameterValue();
    tmpParamet.setWorkflowStepID(stepID);
    tmpParamet.setParameterName(name);
    tmpParamet.setParameterValue(value);
    tmpParamet.setParameterType(paramType);
    wfStepParameterDAO.insertObject(tmpParamet);
  }
  //end
  /**
   * Insert route of this step into Workflow_Step_Routine by stepID
   * @param request
   * @param stepID
   * @throws ApplicationException
   */
  private void insertWorkflowStepRoutine(
        HttpServletRequest request,
        Integer stepID) throws ApplicationException {
    WorkflowStepRouteDAObject wfStepRouteDAO = (WorkflowStepRouteDAObject) this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.WorkflowStepRouteDAObject");

    //  Insert route name into Workflow_Step_Route table
    String  routeListValue = request.getParameter("routeListValue");
    if(!Utility.isEmpty(routeListValue) && !"null".equals(routeListValue) ){
        String[] routineArr = TextUtility.splitString(routeListValue,"|");
        for(int i=0; i<routineArr.length; i++){
          WorkflowStepRoute tmpRoutine = new WorkflowStepRoute();
          tmpRoutine.setWorkflowStepID(stepID);
          tmpRoutine.setRouteSeq(new Integer(i));
          tmpRoutine.setRouteName(routineArr[i]);
          wfStepRouteDAO.insertObject(tmpRoutine);
        }
      }

  }

  /**
   * Insert Wrokflow Step Form Equation
   * @param request
   * @param stepID
   * @throws ApplicationException
   */
  private void insertWorkflowStepFormEquat(
        HttpServletRequest request,
        Integer stepID) throws ApplicationException {
    WorkflowStepFormEquatDAObject formEquatDAO = (WorkflowStepFormEquatDAObject) this.getDAObjectByClassName(request, "com.dcivision.workflow.dao.WorkflowStepFormEquatDAObject");

    //Insert the form equation into Workflow_Step_Form_Equation Table
    String formEquationListValue = request.getParameter("formEquationListValue");

    String[] formEquationArr = TextUtility.splitString(formEquationListValue, "$$");
    for(int i=0; i<formEquationArr.length; i++){
      String[] elementArr = TextUtility.splitString(formEquationArr[i],";");
      //if(!Utility.isEmpty(compare)){
        WorkflowStepFormEquat formEquat = new WorkflowStepFormEquat();
        formEquat.setWorkflowStepID(stepID);
        formEquat.setRouteSeq(new Integer(i+1));
        formEquat.setRouteName(elementArr[0]);
        formEquat.setDefaultFlag(elementArr[1]);
        formEquat.setOperand1(elementArr[2]);
        formEquat.setOperand2(elementArr[3]);
        formEquat.setCompare(elementArr[4]);
        formEquat.setFormEquation(elementArr[5]);
        formEquat.setOperationType(elementArr[6]);
        formEquat.setDateFormat(elementArr[7]);
        formEquatDAO.insertObject(formEquat);

      //}

    }

  }

  /**
   * retrieve Move Step Info
   * @param form
   * @param request
   * @param currentStepID
   * @param parentStepID
   * @throws ApplicationException
   */
  private void retrieveMoveStepInfo(
        AbstractActionForm form,
        HttpServletRequest request,
        Integer currentStepID,
        Integer parentStepID ) throws ApplicationException {
    WorkflowStepDAObject wfStepDAO = new WorkflowStepDAObject(this.getSessionContainer(request),this.getConnection(request));
    MaintWorkflowStepForm maintForm = (MaintWorkflowStepForm)form;

    WorkflowStep currentStep = (WorkflowStep)wfStepDAO.getObjectByID(currentStepID);
    WorkflowStep parentStep = (WorkflowStep)wfStepDAO.getObjectByID(parentStepID);

    maintForm.setStepName(currentStep.getStepName());
    maintForm.setStepID(currentStepID.toString());

    maintForm.setParentStepName(parentStep.getStepName());
    maintForm.setParentStepID(parentStepID.toString());
  }

  /**
   * TODO if current step have move different child step, get they to list ,return;
   * @param currentStepID
   * @param request
   * @return
   * @throws ApplicationException
   */
  private List getNextStepByCurrentStepID(Integer currentStepID, HttpServletRequest request) throws ApplicationException{
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.getSessionContainer(request),this.getConnection(request));
    List stepList = stepDAO.getDistinctListByParentStepID(currentStepID);
    List nextStepInfoList = new ArrayList();
    for (int i = 0; stepList.size() > 1 && i < stepList.size(); i++) {
      //  if current step have more one child step
      WorkflowStep workflowStep = (WorkflowStep)stepList.get(i);
      String[] aOption = new String[2];
      aOption[1] = workflowStep.getStepSeq().toString() + "." + workflowStep.getStepName();
      aOption[0] = workflowStep.getID().toString();
      nextStepInfoList.add(aOption);
    }
    return nextStepInfoList;
  }

  /**
   * setup the priority rule for this step priority.
   * insert record into Mtm_WF_Step_Priority_Rule table.
   * @param request
   * @param form
   * @param stepID
   * @throws ApplicationException
   */
  private void insertWorkflowStepPriorityRule(
      HttpServletRequest request,
      AbstractActionForm form,
      Integer stepID) throws ApplicationException {
    MtmWorkflowStepPriorityRuleDAObject ruleDAO = new MtmWorkflowStepPriorityRuleDAObject(this.getSessionContainer(request),this.getConnection(request));
    MaintWorkflowStepForm maintForm = (MaintWorkflowStepForm)form;

    String ruleListValue = maintForm.getPriorityRuleListValue();
    if(!Utility.isEmpty(ruleListValue)){
      String[] ruleArr = TextUtility.splitString(ruleListValue, "|");
      for(int i=0; i<ruleArr.length; i++){
        String[] tmpRuleArr = TextUtility.splitString(ruleArr[i], ",");
        String ackMethod = "";
        MtmWorkflowStepPriorityRule priorityRule = new MtmWorkflowStepPriorityRule();

        priorityRule.setWorkflowStepID(stepID);
        priorityRule.setEscalateAtAmt(TextUtility.parseIntegerObj(tmpRuleArr[0]) );
        priorityRule.setEscalateAtField(TextUtility.parseIntegerObj(tmpRuleArr[1]) );
        priorityRule.setEscalateTrigger(tmpRuleArr[2]);
        priorityRule.setEscalateLevel(TextUtility.parseIntegerObj(tmpRuleArr[3]) );

        if(!"null".equals(tmpRuleArr[4])){
          ackMethod = tmpRuleArr[4];
        }
        if(!"null".equals(tmpRuleArr[5])) {
          if(Utility.isEmpty(ackMethod)){
            ackMethod = tmpRuleArr[5];
          } else {
            ackMethod += "," + tmpRuleArr[5];
          }
        }
        priorityRule.setEscalateAckMethod(ackMethod);
        ruleDAO.insertObject(priorityRule);

      }
    }
  }
  
  /**
   * Add By Dick
   * TODO inssert notification rules for workflow step notification
   * @param request
   * @param form
   * @param stepID
   * @throws ApplicationException
   */
  private void insertWorkflowStepNotificationRule(
      HttpServletRequest request,
      AbstractActionForm form,
      Integer stepID) throws ApplicationException {
    MtmWfStepNotificationRuleDAObject notificationRuleDAO = new MtmWfStepNotificationRuleDAObject(this.getSessionContainer(request),this.getConnection(request));
    MtmWfStepNotificationTargetDAObject notificationTargetDAO = new MtmWfStepNotificationTargetDAObject(this.getSessionContainer(request),this.getConnection(request));
    MaintWorkflowStepForm maintForm = (MaintWorkflowStepForm)form;

    String NotifyRuleListValue = maintForm.getNotificationRuleListValue();
    if ((!Utility.isEmpty(NotifyRuleListValue) ) && (!"null".equals(NotifyRuleListValue))  ){
      String[] ruleArr = TextUtility.splitString(NotifyRuleListValue, "|");
      for(int i=0; i<ruleArr.length; i++){
        String[] tmpRuleArr = TextUtility.splitString(ruleArr[i], ",");
        String ackMethod = "";
        MtmWfStepNotificationRule notificationRule = new MtmWfStepNotificationRule();

        notificationRule.setWorkflowStepID(stepID);
        notificationRule.setNotifyTrigger(tmpRuleArr[0]);
        notificationRule.setNotifyAtAmt(TextUtility.parseIntegerObj(tmpRuleArr[1]));
        notificationRule.setNotifyAtField(TextUtility.parseIntegerObj(tmpRuleArr[2]) );

        if(!"null".equals(tmpRuleArr[3])){
          ackMethod = tmpRuleArr[3];
        }
        if(!"null".equals(tmpRuleArr[4])) {
          if(Utility.isEmpty(ackMethod)){
            ackMethod = tmpRuleArr[4];
          } else {
            ackMethod += "," + tmpRuleArr[4];
          }
        }
        notificationRule.setNotifyAckMethod(ackMethod);
        notificationRule = (MtmWfStepNotificationRule)notificationRuleDAO.insertObject(notificationRule);
        //insert table MTM_WF_STEP_WF_NOTIFICATION_TARGER
        String notificationOwnerStr = tmpRuleArr[5];
        if (!Utility.isEmpty(notificationOwnerStr)) {
          String[] notificationOwnerElements = TextUtility.splitString(notificationOwnerStr, ":");
          for (int j = 0;j < notificationOwnerElements.length; j++) {
            String[] notificationOwnerElement = TextUtility.splitString(notificationOwnerElements[j], "$");
            MtmWfStepNotificationTarget notificationTarget = new MtmWfStepNotificationTarget();
            notificationTarget.setNotifyRuleID(notificationRule.getID());
            notificationTarget.setTargetType(notificationOwnerElement[2]);
            if ("-1".equals(notificationOwnerElement[0])) {// if notificationOwnerElement[0] equals "-1" expain owner is current step is owner
              notificationTarget.setTargetID(stepID);
            } else {
              notificationTarget.setTargetID(new Integer(notificationOwnerElement[0]));
            }
            notificationTargetDAO.insertObject(notificationTarget);
          }
        }
      }
    }
  }


  private boolean checkObjectStepIsSuperStep(Integer objectStepID, Integer currentStepID, HttpServletRequest request) throws ApplicationException {
    WorkflowRetrievalManager retrievalManager = new WorkflowRetrievalManager(this.getSessionContainer(request), this.getConnection(request));
    List childStepList = new ArrayList();
    childStepList = retrievalManager.getChildStepList(objectStepID, childStepList);
    for (int i = 0; i < childStepList.size(); i++) {
      WorkflowStep workflowStep = (WorkflowStep)childStepList.get(i);
      if (workflowStep.getID().equals(currentStepID)) {
        return true;
      }
    }
    return false;
  }

  private boolean checkHaveCollocateSteps(Integer beginStepID, HttpServletRequest request)throws ApplicationException {
    MtmWorkflowStepWorkflowStepDAObject stepStepDAO = new MtmWorkflowStepWorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
    WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(this.getSessionContainer(request), this.getConnection(request));
    List stepStepList = stepStepDAO.getListByParentStepID(beginStepID);
    if (stepStepList.size() <= 1) {
      MtmWorkflowStepWorkflowStep stepStep = (MtmWorkflowStepWorkflowStep)stepStepList.get(0);
      WorkflowStep childStep = (WorkflowStep)stepDAO.getObjectByID(stepStep.getChildStepID());
      if (!WorkflowStep.ACTION_TYPE_END.equals(childStep.getActionType()) && !GlobalConstant.TRUE.equals(stepStep.getLoopBack())) {
        return this.checkHaveCollocateSteps(childStep.getID(), request);
      }
    } else {
      for (int i = 0; i < stepStepList.size(); i++) {
        MtmWorkflowStepWorkflowStep stepStep = (MtmWorkflowStepWorkflowStep)stepStepList.get(i);
        if (WorkflowStep.PARENT_TYPE_SINGLE.equals(stepStep.getParentType())) {
          return true;
        } else {
          WorkflowStep childStep = (WorkflowStep)stepDAO.getObjectByID(stepStep.getChildStepID());
          if (!WorkflowStep.ACTION_TYPE_END.equals(childStep.getActionType()) && !GlobalConstant.TRUE.equals(stepStep.getLoopBack())) {
            return this.checkHaveCollocateSteps(childStep.getID(), request);
          }
        }
      }
    }
    return false;
  }


  /**
   * insert the bind form into MTM_WF_Step_Form_Record Table
   * @param stepID
   * @param form
   * @param request
   * @throws ApplicationException
   */
  private void insertBindForm(Integer stepID, AbstractActionForm form, HttpServletRequest request)throws ApplicationException {
  	MtmWfStepFormRecordDAObject stepFormRecordDAO = new MtmWfStepFormRecordDAObject(this.getSessionContainer(request), this.getConnection(request));
  	
  	//get the permission. 
  	//the formRecordPermission / formPagePermission / formSectionPermission /formElementPermission define in IncludeBindForm.jsp
  	String[] formRecordPermissionArr = request.getParameterValues("formRecordPermission");
  	String[] formPagePermissionArr = request.getParameterValues("formPagePermission");
    String[] formSectionPermissionArr = request.getParameterValues("formSectionPermission");  	
  	String[] formElementPermissionArr = request.getParameterValues("formElementPermission");
  	
    //because the name is auto generated, so only the reqeust.getParameter() 
  	//process Form Record
  	for (int i=0; !Utility.isEmpty(formRecordPermissionArr) && i<formRecordPermissionArr.length; i++) {
  		log.debug("========== Form ======"+formRecordPermissionArr[i] +":"+request.getParameter(formRecordPermissionArr[i]));
  		if(Utility.isEmpty(request.getParameter(formRecordPermissionArr[i])) ){  		  
  			continue;
  		}
  		
  		MtmWfStepFormRecord tmpStepFormRecord = new MtmWfStepFormRecord();
  		tmpStepFormRecord.setWorkflowStepID(stepID);
  		tmpStepFormRecord.setFormRecordID(new Integer(formRecordPermissionArr[i].substring(1)) );
  		tmpStepFormRecord.setMandatory(GlobalConstant.FALSE);
  		tmpStepFormRecord.setPermission(request.getParameter(formRecordPermissionArr[i]));
  		stepFormRecordDAO.insertObject(tmpStepFormRecord);
  	}
  	
  	//process Form Page
  	for (int i=0; !Utility.isEmpty(formPagePermissionArr) && i<formPagePermissionArr.length; i++) {
  		log.debug("========== Page ======"+formPagePermissionArr[i]+":"+request.getParameter(formPagePermissionArr[i]));
  		if(Utility.isEmpty(request.getParameter(formPagePermissionArr[i])) ){  		  
  			continue;
  		}
  		
  		String[] IDArr = formPagePermissionArr[i].substring(1).split("_");        
  		
  		MtmWfStepFormRecord tmpStepFormRecord = new MtmWfStepFormRecord();
  		tmpStepFormRecord.setWorkflowStepID(stepID);
  		tmpStepFormRecord.setFormRecordID(new Integer(IDArr[0] ) );
  		tmpStepFormRecord.setFormPageID(new Integer(IDArr[1] ) );
  		tmpStepFormRecord.setMandatory(GlobalConstant.FALSE);
  		tmpStepFormRecord.setPermission(request.getParameter(formPagePermissionArr[i]));
  		stepFormRecordDAO.insertObject(tmpStepFormRecord);
  	}
  	
  	
  	//process Form Section
  	for (int i=0; !Utility.isEmpty(formSectionPermissionArr) && i<formSectionPermissionArr.length; i++) {
  		log.debug("========== Section ======"+formSectionPermissionArr[i]+":"+request.getParameter(formSectionPermissionArr[i]));
  		if(Utility.isEmpty(request.getParameter(formSectionPermissionArr[i])) ){  		  
  			continue;
  		}
  		
  		String[] IDArr = formSectionPermissionArr[i].substring(1).split("_");        
  		
  		MtmWfStepFormRecord tmpStepFormRecord = new MtmWfStepFormRecord();
  		tmpStepFormRecord.setWorkflowStepID(stepID);
  		tmpStepFormRecord.setFormRecordID(new Integer(IDArr[0] ) );
  		tmpStepFormRecord.setFormPageID(new Integer(IDArr[1] ) );
  		tmpStepFormRecord.setFormSectionID(new Integer(IDArr[2] ) );
  		tmpStepFormRecord.setMandatory(GlobalConstant.FALSE);
  		tmpStepFormRecord.setPermission(request.getParameter(formSectionPermissionArr[i]));
  		stepFormRecordDAO.insertObject(tmpStepFormRecord);
  	}
  		
  	
  	//process Form Element
  	for (int i=0; !Utility.isEmpty(formElementPermissionArr) && i<formElementPermissionArr.length; i++) {
  		log.debug("========== Element ======"+formElementPermissionArr[i]+":"+request.getParameter(formElementPermissionArr[i]));   		
  		if(Utility.isEmpty(request.getParameter(formElementPermissionArr[i])) ){  		  
  			continue; 
  		}
  		
  		String[] IDArr = formElementPermissionArr[i].substring(1).split("_");        
  		MtmWfStepFormRecord tmpStepFormRecord = new MtmWfStepFormRecord();
  		tmpStepFormRecord.setWorkflowStepID(stepID);
  		tmpStepFormRecord.setFormRecordID(new Integer(IDArr[0] ) );
  		tmpStepFormRecord.setFormPageID(new Integer(IDArr[1] ) );
  		tmpStepFormRecord.setFormSectionID(new Integer(IDArr[2] ) );
  		tmpStepFormRecord.setFormElementID(new Integer(IDArr[3] ) );
  		tmpStepFormRecord.setMandatory(GlobalConstant.FALSE);
  		tmpStepFormRecord.setPermission(request.getParameter(formElementPermissionArr[i]));
  		stepFormRecordDAO.insertObject(tmpStepFormRecord);
  	}
  	

  }


  private void insertProtectedResourceInfo(
      HttpServletRequest request,
      AbstractActionForm form,
      WorkflowStep workflowStep) throws ApplicationException {
    ProtectedResourceDAObject protectedResouceDAO = new ProtectedResourceDAObject(this.getSessionContainer(request),this.getConnection(request));
    MaintWorkflowStepForm maintForm = (MaintWorkflowStepForm)form;

    if(GlobalConstant.TRUE.equals(maintForm.getProtectedStep())) {
      ProtectedResource protectedResource= new ProtectedResource();
      protectedResource.setHelperClass(HELPER_CLASS);
      String navModeEditBuff = null;
      String opModeBuffEditBuff = null;
      if (!Utility.isEmpty(maintForm.getProtectedOpModeEdit())) {
        opModeBuffEditBuff = maintForm.getProtectedOpModeEdit();
      }
      if (!Utility.isEmpty(opModeBuffEditBuff) && !Utility.isEmpty(maintForm.getProtectedOpModeView())) {
        opModeBuffEditBuff += "|" + maintForm.getProtectedOpModeView();
      } else if(!Utility.isEmpty(maintForm.getProtectedOpModeView())) {
        opModeBuffEditBuff = maintForm.getProtectedOpModeView();
      }
      if (!Utility.isEmpty(maintForm.getProtectedNavModeEdit())) {
        navModeEditBuff = maintForm.getProtectedNavModeEdit();
      }
      if (!Utility.isEmpty(navModeEditBuff) && !Utility.isEmpty(maintForm.getProtectedNavModeView())) {
        navModeEditBuff += "|" + maintForm.getProtectedNavModeView();
      } else if(!Utility.isEmpty(maintForm.getProtectedNavModeView())) {
        navModeEditBuff = maintForm.getProtectedNavModeView();
      }
      protectedResource.setNavMode(navModeEditBuff);
      protectedResource.setOpMode(opModeBuffEditBuff);
      protectedResource.setUrlPattern("workflow/MaintWorkflowTask.do");
      ProtectedResource DAOProtectedResource = (ProtectedResource)protectedResouceDAO.insertObject(protectedResource);
      this.insertProtectedObejctInfoRelatedToProtectedResource(request, form, workflowStep, DAOProtectedResource.getID());
      
      // A start step also will be protected by the url pattern("workflow/MaintWorkflowSubmission.do").
      if (WorkflowStep.START_STEP_SEQ_NO.equals(workflowStep.getStepSeq())) {
        protectedResource.setUrlPattern("workflow/MaintWorkflowSubmission.do");
        ProtectedResource startStepDAOProtectedResource = (ProtectedResource)protectedResouceDAO.insertObject(protectedResource);
        this.insertProtectedObejctInfoRelatedToProtectedResource(request, form, workflowStep, startStepDAOProtectedResource.getID());
      }
// Commented by Brook.Huang. 
//      if (WorkflowStep.START_STEP_SEQ_NO.equals(workflowStep.getStepSeq())) {
//        protectedResource.setUrlPattern("workflow/MaintWorkflowSubmission.do");
//      } else {
//        protectedResource.setUrlPattern("workflow/MaintWorkflowTask.do");
//      }
    }
  }
  
  /**
   * 
   * @param request
   * @param form
   * @param workflowStep
   * @param relatedProtectedResourceID
   * @throws ApplicationException
   */
  private void insertProtectedObejctInfoRelatedToProtectedResource(HttpServletRequest request,
      AbstractActionForm form,
      WorkflowStep workflowStep,
      Integer relatedProtectedResourceID) throws ApplicationException {
    ProtectedObjectDAObject protectedObjectDAO = new ProtectedObjectDAObject(this.getSessionContainer(request),this.getConnection(request));
    MaintWorkflowStepForm maintForm = (MaintWorkflowStepForm)form;
    
    ProtectedObject protectedObject = new ProtectedObject();
    protectedObject.setObjectValue(workflowStep.getID().toString());
    if (!Utility.isEmpty(maintForm.getAuthenticatePassword())) {
      protectedObject.setProtection(maintForm.getAuthenticatePassword());
    } else {
      protectedObject.setProtection((String)null);
    }
    protectedObject.setResourceID(relatedProtectedResourceID);
    protectedObject = (ProtectedObject)protectedObjectDAO.insertObject(protectedObject);
  }
  
  /**
   * @ToDo deleteProtectedResourceInfo
   * @param request
   * @param stepID
   * @throws ApplicationException
   */
  private void deleteProtectedResourceInfo(
      HttpServletRequest request,
      Integer stepID) throws ApplicationException {
    ProtectedResourceDAObject protectedResouceDAO = new ProtectedResourceDAObject(this.getSessionContainer(request),this.getConnection(request));
    ProtectedObjectDAObject protectedObjectDAO = new ProtectedObjectDAObject(this.getSessionContainer(request),this.getConnection(request));
    List oldProtectedObjectList = protectedObjectDAO.getListByObjectValue(stepID);
    for (int i = 0; !Utility.isEmpty(oldProtectedObjectList) && i < oldProtectedObjectList.size(); i++) {
      ProtectedObject currentObject = (ProtectedObject)oldProtectedObjectList.get(i);
      protectedResouceDAO.deleteObjectByID(currentObject.getResourceID());
      protectedObjectDAO.deleteObject(currentObject);
    }
  }

  private void getProtectedResourceInfo(
      HttpServletRequest request,
      AbstractActionForm form,
      Integer stepID) throws ApplicationException {
    MaintWorkflowStepForm workflowStepForm = (MaintWorkflowStepForm)form;
    ProtectedResourceDAObject protectedResouceDAO = new ProtectedResourceDAObject(this.getSessionContainer(request),this.getConnection(request));
    ProtectedObjectDAObject protectedObjectDAO = new ProtectedObjectDAObject(this.getSessionContainer(request),this.getConnection(request));
    // TODO: Should we check whether the protected object is related to the step
    // just by object's id? problem will taken if there are multiply type of
    // protected object recorded in the same DB table.
    List oldProtectedObjectList = protectedObjectDAO.getListByObjectValue(stepID);
    for (int i = 0; !Utility.isEmpty(oldProtectedObjectList) && i < oldProtectedObjectList.size(); i++) {
      ProtectedObject currentObject = (ProtectedObject)oldProtectedObjectList.get(i);
      ProtectedResource protectedResource = (ProtectedResource)protectedResouceDAO.getObjectByID(currentObject.getResourceID());
      workflowStepForm.setProtectedStep(GlobalConstant.TRUE);
      if (!Utility.isEmpty(protectedResource.getNavMode())) {
        if (protectedResource.getNavMode().indexOf(GlobalConstant.NAV_MODE_EDIT) >=  0) {
          workflowStepForm.setProtectedNavModeEdit(GlobalConstant.NAV_MODE_EDIT);
        }
        if (protectedResource.getNavMode().indexOf(GlobalConstant.NAV_MODE_VIEW) >=  0) {
          workflowStepForm.setProtectedNavModeView(GlobalConstant.NAV_MODE_VIEW);
        }
      }
      if (!Utility.isEmpty(protectedResource.getOpMode())) {
        if (protectedResource.getOpMode().indexOf(GlobalConstant.NAV_MODE_EDIT) >=  0) {
          workflowStepForm.setProtectedOpModeEdit(GlobalConstant.NAV_MODE_EDIT);
        }
        if (protectedResource.getOpMode().indexOf(GlobalConstant.NAV_MODE_VIEW) >=  0) {
          workflowStepForm.setProtectedOpModeView(GlobalConstant.NAV_MODE_VIEW);
        }
      }
      if (!Utility.isEmpty(currentObject.getProtection())) {
        workflowStepForm.setAuthenticatePassword(Crypt.decrypt(currentObject.getProtection(), SystemParameterFactory.getSystemParameter(SystemParameterConstant.CRYPTO_SALT)));
      }
    }
  }

  /**
   * get the working calendar list.
   * @param request
   * @throws ApplicationException
   */
  private void getWorkingCalendarList(HttpServletRequest request) throws ApplicationException {
    WorkingCalendarDAObject workingCalDAO = new WorkingCalendarDAObject(this.getSessionContainer(request), this.getConnection(request));
    List workingCalList = workingCalDAO.getFullList();
    request.setAttribute("WORKING_CALENDAR_LIST", workingCalList);    
  }
  
  /**
   * get the stage array 
   * @param request
   * @param form
   * @throws ApplicationException
   */
  private void getStageArray(HttpServletRequest request, ActionForm form) throws ApplicationException {
    WorkflowStageDAObject stageDAO = new WorkflowStageDAObject(this.getSessionContainer(request), this.getConnection(request));
    
    MaintWorkflowStepForm workflowStepForm = (MaintWorkflowStepForm)form;    
    List stageList = stageDAO.getListByWorkflowRecordID(new Integer(workflowStepForm.getWorkflowRecordID()) );    
    
    String[][] stageArr = new String[stageList.size()+1][2];
    stageArr[0][0] = MessageResourcesFactory.getMessage(this.getLocale(request), "common.options.select_menu.select_one");
    stageArr[0][1] = "";
    for (int i = 0; i < stageList.size(); i++) {
      WorkflowStage stage = (WorkflowStage)stageList.get(i);
      stageArr[i + 1][0] = stage.getStageName();
      stageArr[i + 1][1] = stage.getID().toString();
    }
    
    workflowStepForm.setStageArray(stageArr);
  }
  
  /**
   * update workflow stage
   * @param request
   * @param form
   * @param workflowStepID
   * @throws ApplicationException
   */
  private void updateWorkflowStage(HttpServletRequest request, ActionForm form, Integer workflowStepID) throws ApplicationException {
    MaintWorkflowStepForm workflowStepForm = (MaintWorkflowStepForm)form;
    WorkflowStageDAObject stageDAO = new WorkflowStageDAObject(this.getSessionContainer(request), this.getConnection(request));
    
    MtmWfStageWfStepDAObject stageStepDAO = new MtmWfStageWfStepDAObject(this.getSessionContainer(request), this.getConnection(request));
    
    //remove the workflow stage
    MtmWfStageWfStep stageStep = (MtmWfStageWfStep) stageStepDAO.getObjectByWorkflowStepID(workflowStepID);
    if (!Utility.isEmpty(stageStep)){
      stageStepDAO.physicDelete(stageStep);
    } 
    
    //insert the workflwo stage
    if( !Utility.isEmpty(workflowStepForm.getWorkflowStageID()) ){      
      this.insertWorkflowStage(request, form, workflowStepID);
    }
    
    
  }
  
  /**
   * insert workflow stage
   * @param request
   * @param form
   * @param workflowStepID
   * @throws ApplicationException
   */
  private void insertWorkflowStage(HttpServletRequest request, ActionForm form, Integer workflowStepID) throws ApplicationException {
    MaintWorkflowStepForm workflowStepForm = (MaintWorkflowStepForm)form;   
    MtmWfStageWfStepDAObject stageStepDAO = new MtmWfStageWfStepDAObject(this.getSessionContainer(request), this.getConnection(request));
    
    if( !Utility.isEmpty(workflowStepForm.getWorkflowStageID()) ){
      MtmWfStageWfStep stageStep = new MtmWfStageWfStep();
      stageStep.setWorkflowStageID(new Integer(workflowStepForm.getWorkflowStageID()) );
      stageStep.setWorkflowStepID(workflowStepID);      
      stageStepDAO.insertObject(stageStep);      
    }
    
  }
  
  /**
   * update workflow_record update_count/update_date/updater_ID
   * @param request
   * @param workflowRecordID
   * @throws ApplicationException
   */
  private void updateWorkflowRecord(HttpServletRequest request,Integer workflowRecordID) throws ApplicationException{
    if(!Utility.isEmpty(workflowRecordID)){
      WorkflowRecordDAObject recordDAO = new WorkflowRecordDAObject(this.getSessionContainer(request),this.getConnection(request));
      WorkflowRecord record = (WorkflowRecord)recordDAO.getObjectByID(workflowRecordID);
      recordDAO.updateObject(record);
    }
  }
}